<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .error {
        color: red;
        display: none;
      }
    </style>
  </head>
  <body>
    <form name="form">
      <p>
        用户
        <input type="text" name="username" />
        <span class="error error-username">用户名必须3-18字符</span>
      </p>
      <p>
        手机
        <input type="text" name="phone" />
        <span class="error error-phone">手机格式错误</span>
      </p>
      <p>
        邮箱
        <input type="text" name="email" />
        <span class="error error-email">邮箱格式错误</span>
      </p>

      <p>
        年龄
        <input type="text" name="age" />
        <span class="error error-age">年龄必须10-80</span>
      </p>
      <p>
        性别
        <input type="radio" name="gender" value="1" checked /> 男
        <input type="radio" name="gender" value="2" /> 女
      </p>

      <p>
        爱好
        <input type="checkbox" name="hobby" value="css" checked />CSS
        <input type="checkbox" name="hobby" value="html" />HTML
        <input type="checkbox" name="hobby" value="js" />JS
        <span class="error error-hobby">必须选择一个爱好</span>
      </p>
      <p>
        <button type="button" data-action="submit">提交</button>
      </p>
    </form>
    <script>
      const form = document.form;

      function valid(node, cb) {
        // 1. 获取验证字符
        const value = node.value;
        // 2. 执行验证规则
        const res = cb(value, node);

        let name = "";
        // 3. 判断表单元素的类别
        if (node.length) {
          name = node[0].name;
        } else {
          name = node.name;
        }
        const errorNode = document.querySelector(`.error-${name}`);

        if (res) {
          errorNode.style.display = "";
        } else {
          errorNode.style.display = "inline";
        }

        return res;
      }

      const actions = {
        submit() {
          let flag = true;
          // 用户名
          flag =
            valid(form.username, (value) => {
              const reg = /^[a-z]{3,18}$/;
              return reg.test(value);
            }) && flag;

          // 手机
          flag =
            valid(form.phone, (value) => {
              const reg = /^(?:(?:\+|00)86)?1[3-9]\d{9}$/;
              return reg.test(value);
            }) && flag;
          // 邮箱
          flag =
            valid(form.email, (value) => {
              const reg =
                /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
              return reg.test(value);
            }) && flag;

          // 年龄
          flag =
            valid(form.age, (value) => {
              return value >= 10 && value <= 80;
            }) && flag;

          // 爱好
          flag =
            valid(form.hobby, (value, node) => {
              const nodes = [...node].filter((el) => el.checked);
              return nodes.length > 0;
            }) && flag;

          if (flag) {
            console.log("添加成功");
          }
        },
      };

      form.oninput = function (e) {
        const name = e.target.name;
        if (name === "username") {
          valid(e.target, (value) => {
            const reg = /^[a-z]{3,18}$/;
            return reg.test(value);
          });
        }
        if (name === "email") {
          valid(form.email, (value) => {
            const reg =
              /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
            return reg.test(value);
          });
        }
        if (name === "phone") {
          valid(e.target, (value) => {
            const reg = /^(?:(?:\+|00)86)?1[3-9]\d{9}$/;
            return reg.test(value);
          });
        }
        if (name === "age") {
          valid(form.age, (value) => {
            return value >= 10 && value <= 80;
          });
        }
        if (name === "hobby") {
          valid(form.hobby, (value, node) => {
            const nodes = [...node].filter((el) => el.checked);
            return nodes.length > 0;
          });
        }
      };

      form.onclick = function (e) {
        const action = e.target.dataset.action;
        if (action === undefined || actions[action] === undefined) return;
        actions[action].call(e.target);
      };
    </script>
  </body>
</html>
